package net.apps.core.meta;

import java.util.Collection;
import java.util.Collections;

import net.apps.core.meta.Meta.Decl;


public class MetaFactory {

	public static final Meta metaOfMeta;
	public static final Meta metaOfProtocol;
	public static final Meta metaOfDecl;
	public static final Meta metaOfField;
	static {
		metaOfMeta = new MetaMetaImpl(Decl.META, Meta.ID_META_OF_META, "MetaOfMeta", null, null);
		metaOfProtocol = new MetaMetaImpl(Decl.META, Meta.ID_META_OF_PROTO, "MetaOfProtocol", null, null);
		metaOfDecl = new MetaMetaImpl(Decl.META, Meta.ID_META_OF_DECL, "MetaOfDecl", null, null);
		metaOfField = new MetaMetaImpl(Decl.META, Meta.ID_META_OF_FIELD, "MetaOfField", null, null);
		((MetaMetaImpl)metaOfMeta).typedecls[Meta.ID_META_OF_META] = metaOfMeta;
		((MetaMetaImpl)metaOfMeta).typedecls[Meta.ID_META_OF_PROTO] = metaOfProtocol;
		((MetaMetaImpl)metaOfMeta).typedecls[Meta.ID_META_OF_DECL] = metaOfDecl;
		((MetaMetaImpl)metaOfMeta).typedecls[Meta.ID_META_OF_FIELD] = metaOfField;
	}
	
	private static final class MetaMetaImpl implements Meta {
		private final Decl decl;
		private final int id;
		private final Meta type;
		private final Meta parent;
		private final Meta[] typedecls;
		private final String name;
		private final String description;
		private final Object value;
		
		public MetaMetaImpl(Decl decl, int id, String name, String description, Object value) {
			this.decl = decl;
			this.id = id;
			if (id == Meta.ID_META_OF_META) {
				this.type = this;
				this.parent = null;
				this.typedecls = new Meta[4];
			} else {
				this.type = metaOfMeta;
				this.parent = metaOfMeta;
				this.typedecls = new Meta[0];
			}
			this.name = name;
			this.description = description;
			this.value = value;
		}
		public Decl getDeclKind() { return decl; }
		public int getId() { return id; }
		public Meta getType() { return type; }
		public Collection<Meta> getConstraints() { return Collections.emptyList(); }
		public String getName() { return name; }
		public String getDescription() { return description; }
		public Meta getParent() { return parent; }
		public Collection<Meta> getDecls() { return Collections.emptyList(); }
		public Meta getTypeDecl(int id) { return typedecls[id]; }
		public Object getValue() { return value; }
	}
}
